/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file    can.c
  * @brief   This file provides code for the configuration
  *          of the CAN instances.
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2024 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "can.h"

/* USER CODE BEGIN 0 */
#define CAN_POLLING_NUMBER    5u


typedef struct
{
    CAN_TxHeaderTypeDef txHeaderType;
    uint8_t txMessageBuffer[8];
}TX_MESSAGE_TYPE_S;

typedef struct
{
    CAN_RxHeaderTypeDef rxHeaderType;
    uint8_t rxMessageBuffer[8];
}RX_MESSAGE_TYPE_S;


typedef struct
{
    CAN_TxHeaderTypeDef t_canHeader;
    uint8* bufferPtr;
    uint8_t u8_indication;
}CAN_FRAME_TX_INFO_S;


typedef struct
{
    CAN_RxHeaderTypeDef t_canHeader;
    uint8_t u8_buffer[8];
    uint8_t u8_indication;
}CAN_FRAME_RX_INFO_S;


typedef struct
{
    CAN_FRAME_TX_INFO_S s_canTxFrameInfo[CAN_POLLING_NUMBER];
    CAN_FRAME_RX_INFO_S s_canRxFrameInfo[CAN_POLLING_NUMBER];
    uint8 u8_frameTxIndex;
    uint8 u8_frameRxIndex;
}CAN_INFO_S;

static CAN_INFO_S s_CanInfo;


TX_MESSAGE_TYPE_S txMessage_Test1;
RX_MESSAGE_TYPE_S rxMessage_Test1;

void CAN_Runnable_1ms(void);
Std_ReturnType Can_Write (
    Can_HwHandleType Hth,
    const Can_PduType* PduInfo
);
void CAN_Read(CAN_HandleTypeDef *hcan);


Std_ReturnType Can_Write (
    Can_HwHandleType Hth,
    const Can_PduType* PduInfo
)
{
    CAN_TxHeaderTypeDef t_canHeaderType;
    uint32 u32_txMailbox;
    
    s_CanInfo.s_canTxFrameInfo[s_CanInfo.u8_frameTxIndex].t_canHeader.StdId = PduInfo->id;
    s_CanInfo.s_canTxFrameInfo[s_CanInfo.u8_frameTxIndex].t_canHeader.DLC = PduInfo->length;
    s_CanInfo.s_canTxFrameInfo[s_CanInfo.u8_frameTxIndex].bufferPtr = PduInfo->sdu;
    s_CanInfo.s_canTxFrameInfo[s_CanInfo.u8_frameTxIndex].u8_indication = SET;
    s_CanInfo.u8_frameTxIndex++;
    
    if(CAN_POLLING_NUMBER <= s_CanInfo.u8_frameTxIndex)
    {
        s_CanInfo.u8_frameTxIndex = 0u;
    }
}


void CAN_Read(CAN_HandleTypeDef *hcan)
{
    HAL_CAN_GetRxFifoFillLevel(hcan, CAN_RX_FIFO0);
    HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &(s_CanInfo.s_canRxFrameInfo[s_CanInfo.u8_frameRxIndex].t_canHeader),  s_CanInfo.s_canRxFrameInfo[s_CanInfo.u8_frameRxIndex].u8_buffer);
    s_CanInfo.s_canRxFrameInfo[s_CanInfo.u8_frameRxIndex].u8_indication = SET;
    
    s_CanInfo.u8_frameRxIndex++;
    if(CAN_POLLING_NUMBER <= s_CanInfo.u8_frameRxIndex)
    {
        s_CanInfo.u8_frameRxIndex = 0u;
    }
}

void Can_MainFunction_Write(void)
{
    uint8 u8_i;
    CAN_FRAME_TX_INFO_S* ptr_canFrameInfo;
    uint32 u32_txMailbox;
    
    for(u8_i = 0; u8_i < CAN_POLLING_NUMBER; u8_i++)
    {
        ptr_canFrameInfo = &s_CanInfo.s_canTxFrameInfo[u8_i];
        if(SET == ptr_canFrameInfo->u8_indication)
        {
            HAL_CAN_AddTxMessage(&hcan, &(ptr_canFrameInfo->t_canHeader), ptr_canFrameInfo->bufferPtr, &u32_txMailbox);
            ptr_canFrameInfo->u8_indication = RESET;
        }
    }
}

void Can_MainFunction_Read(void)
{
    uint8 u8_i;
    CAN_FRAME_RX_INFO_S* ptr_canFrameInfo;
    Can_HwType mailbox;
    PduInfoType pduInfo;

    for(u8_i = 0; u8_i < CAN_POLLING_NUMBER; u8_i++)
    {
        ptr_canFrameInfo = &s_CanInfo.s_canRxFrameInfo[u8_i];
        if(SET == ptr_canFrameInfo->u8_indication)
        {
            mailbox.CanId = ptr_canFrameInfo->t_canHeader.StdId;
            pduInfo.SduLength = ptr_canFrameInfo->t_canHeader.DLC;
            pduInfo.SduDataPtr = ptr_canFrameInfo->u8_buffer;
            CanIf_RxIndication (&mailbox, &pduInfo);

            ptr_canFrameInfo->u8_indication = RESET;
        }
    }
}

void CAN_ConfigFilter(void)
{
    CAN_FilterTypeDef sFilterConfig;

    sFilterConfig.FilterBank = 0;
    sFilterConfig.FilterMode =  CAN_FILTERMODE_IDMASK;     
    sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;  
    		
    sFilterConfig.FilterIdHigh = 0x0000;   
    sFilterConfig.FilterIdLow  = 0x0000;    		
    sFilterConfig.FilterMaskIdHigh = 0;
    sFilterConfig.FilterMaskIdLow  = 0;
    sFilterConfig.FilterFIFOAssignment = CAN_FILTER_FIFO0; 
    
    sFilterConfig.FilterActivation = CAN_FILTER_ENABLE; 
    sFilterConfig.SlaveStartFilterBank  = 0; 
    
    HAL_CAN_ConfigFilter(&hcan, &sFilterConfig);
}


void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
    //CAN_ReceiveMessage(hcan, &rxMessage_Test1);
    CAN_Read(hcan);
}

/* USER CODE END 0 */

CAN_HandleTypeDef hcan;

/* CAN init function */
void MX_CAN_Init(void)
{

  /* USER CODE BEGIN CAN_Init 0 */

  /* USER CODE END CAN_Init 0 */

  /* USER CODE BEGIN CAN_Init 1 */

  /* USER CODE END CAN_Init 1 */
  hcan.Instance = CAN1;
  hcan.Init.Prescaler = 9;
  hcan.Init.Mode = CAN_MODE_NORMAL;
  hcan.Init.SyncJumpWidth = CAN_SJW_1TQ;
  hcan.Init.TimeSeg1 = CAN_BS1_5TQ;
  hcan.Init.TimeSeg2 = CAN_BS2_2TQ;
  hcan.Init.TimeTriggeredMode = DISABLE;
  hcan.Init.AutoBusOff = ENABLE;
  hcan.Init.AutoWakeUp = ENABLE;
  hcan.Init.AutoRetransmission = DISABLE;
  hcan.Init.ReceiveFifoLocked = DISABLE;
  hcan.Init.TransmitFifoPriority = DISABLE;
  if (HAL_CAN_Init(&hcan) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN CAN_Init 2 */
  CAN_ConfigFilter();
  HAL_CAN_Start(&hcan);  
  HAL_CAN_ActivateNotification(&hcan, CAN_IT_RX_FIFO0_MSG_PENDING);
  /* USER CODE END CAN_Init 2 */

}

void HAL_CAN_MspInit(CAN_HandleTypeDef* canHandle)
{

  GPIO_InitTypeDef GPIO_InitStruct = {0};
  if(canHandle->Instance==CAN1)
  {
  /* USER CODE BEGIN CAN1_MspInit 0 */

  /* USER CODE END CAN1_MspInit 0 */
    /* CAN1 clock enable */
    __HAL_RCC_CAN1_CLK_ENABLE();

    __HAL_RCC_GPIOB_CLK_ENABLE();
    /**CAN GPIO Configuration
    PB8     ------> CAN_RX
    PB9     ------> CAN_TX
    */
    GPIO_InitStruct.Pin = GPIO_PIN_8;
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = GPIO_PIN_9;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

    __HAL_AFIO_REMAP_CAN1_2();

    /* CAN1 interrupt Init */
    HAL_NVIC_SetPriority(USB_LP_CAN1_RX0_IRQn, 5, 0);
    HAL_NVIC_EnableIRQ(USB_LP_CAN1_RX0_IRQn);
    HAL_NVIC_SetPriority(CAN1_RX1_IRQn, 5, 0);
    HAL_NVIC_EnableIRQ(CAN1_RX1_IRQn);
  /* USER CODE BEGIN CAN1_MspInit 1 */

  /* USER CODE END CAN1_MspInit 1 */
  }
}

void HAL_CAN_MspDeInit(CAN_HandleTypeDef* canHandle)
{

  if(canHandle->Instance==CAN1)
  {
  /* USER CODE BEGIN CAN1_MspDeInit 0 */

  /* USER CODE END CAN1_MspDeInit 0 */
    /* Peripheral clock disable */
    __HAL_RCC_CAN1_CLK_DISABLE();

    /**CAN GPIO Configuration
    PB8     ------> CAN_RX
    PB9     ------> CAN_TX
    */
    HAL_GPIO_DeInit(GPIOB, GPIO_PIN_8|GPIO_PIN_9);

    /* CAN1 interrupt Deinit */
    HAL_NVIC_DisableIRQ(USB_LP_CAN1_RX0_IRQn);
    HAL_NVIC_DisableIRQ(CAN1_RX1_IRQn);
  /* USER CODE BEGIN CAN1_MspDeInit 1 */

  /* USER CODE END CAN1_MspDeInit 1 */
  }
}

/* USER CODE BEGIN 1 */
void CAN_Runnable_1ms(void)
{
    PduIdType TxPduId = 1;
    PduInfoType PduInfoPtr;
    static uint8 hahaBuffer[8]; 
    static uint8 timerCnt;
 
    Can_MainFunction_Write();
    Can_MainFunction_Read();

#if 0 
    PduInfoPtr.SduLength = 8;
    PduInfoPtr.SduDataPtr = (uint8*)(hahaBuffer);
    PduInfoPtr.SduDataPtr[0] = 0xAA;
    PduInfoPtr.SduDataPtr[7]++;
    
    timerCnt++;
    if(timerCnt >= 100)
    {
        CanIf_Transmit (1, &PduInfoPtr);
        timerCnt = 0;
    }
#endif
}
/* USER CODE END 1 */
